// strictly LRU

var HeaderCache = {};

HeaderCache.cache = null;
HeaderCache.cachesize = 0;
HeaderCache.recency = null;
HeaderCache.maxsize = 25;

HeaderCache.init = function() {
        AppalachianDebug.trace("header-cache.js", "> init");
        HeaderCache.cache = new Object();
        HeaderCache.recency = new Object();
        HeaderCache.observer.register();
        // @@@ use pref setting for maxsize if any exists
        AppalachianDebug.trace("header-cache.js", "< init");
};

HeaderCache.put = function(url, headers) {
        AppalachianDebug.trace("header-cache.js", "> put " + url);
        if (HeaderCache.cachesize > HeaderCache.maxsize) {
                HeaderCache.evict(HeaderCache.cachesize - HeaderCache.maxsize);
        }
        HeaderCache.cachesize++;
        HeaderCache.cache[url] = headers;
        var d = new Date().getTime();
        HeaderCache.recency[d] = url;
        AppalachianDebug.trace("header-cache.js", "< put");
};

HeaderCache.get = function(url) {
        AppalachianDebug.trace("header-cache.js", "> get " + url);
        if (HeaderCache.cache[url]) {
                AppalachianDebug.trace("header-cache.js", "  get hit");
                AppalachianDebug.trace("header-cache.js", "< get");
                return HeaderCache.cache[url];
        } else {
                AppalachianDebug.trace("header-cache.js", "  get miss");
                AppalachianDebug.trace("header-cache.js", "< get");
                return null;
        }
};

HeaderCache.evict = function(count) {
        AppalachianDebug.trace("header-cache.js", "> evict " + count);
        for (var i = 0; i < count; i++) {
                var minUrl = null;
                var min = 0;
                for (var j in HeaderCache.recency) {
                        if (j < min || min == 0) {
                                minUrl = HeaderCache.recency[j];
                                min = j;
                        }
                }
                AppalachianDebug.trace("header-cache.js", "  evict: " + min + " " + minUrl);
                delete HeaderCache.cache[minUrl];
                delete HeaderCache.recency[min];
                HeaderCache.cachesize--;
        }
        AppalachianDebug.trace("header-cache.js", "< evict");
};

HeaderCache.destroy = function() {
        AppalachianDebug.trace("header-cache.js", "> destroy");
        HeaderCache.cache = null;
        HeaderCache.recency = null;
        HeaderCache.observer.unregister();
        AppalachianDebug.trace("header-cache.js", "< destroy");
};

HeaderCache.observer = {
	observe : function(subject, topic, data) {
		AppalachianDebug.trace('header-cache.js','> observe ' + topic);
		if (subject != null) {
			var httpChannel = subject.QueryInterface(Components.interfaces.nsIHttpChannel);
                        var headers = new Object();
                        headers.location = null;
                        headers.isXRDS = false;
			if (topic == "http-on-examine-response") {
                                try {
                                        type = httpChannel.getResponseHeader("Content-Type");
                                        if (type.search(/html/i) >= 0 || type == '*/*') {
                				try {
	                				headers.location = httpChannel.getResponseHeader(YADIS_HTTP_HEADER);
		                		} catch(e) { }
        		        		try {
	        		        		headers.isXRDS = (httpChannel.getResponseHeader(HTTP_CONTENT_TYPE).toLowerCase().indexOf(YADIS_MIME_TYPE) >= 0 || httpChannel.getResponseHeader(HTTP_CONTENT_TYPE).toLowerCase().indexOf(XML_TEXT_MIME_TYPE) >= 0 || httpChannel.getResponseHeader(HTTP_CONTENT_TYPE).toLowerCase().indexOf(XML_APP_MIME_TYPE) >= 0);
		        		        } catch(e) { }
                                                HeaderCache.put(httpChannel.URI.asciiSpec, headers);
                                        }
                                } catch (err) { }
			}
		}
		AppalachianDebug.trace('header-cache.js','< observe');
	},

	register : function() {
		var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
		observerService.addObserver(this, "http-on-examine-response", false);
	},

	unregister : function() {
		var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
		observerService.removeObserver(this, "http-on-examine-response");
	},

	QueryInterface : function(aIID) {
		if (aIID.equals(Components.interfaces.nsISupports) ||
		    aIID.equals(Components.interfaces.nsIObserver))
			return this;
		throw Components.results.NS_NOINTERFACE;
	}
};
